/**
 * \brief   Pistachio-specific dataspace component
 * \date    2006-09-18
 * \author  Christian Helmuth
 * \author  Julian Stecklina
 */

/*
 * Copyright (C) 2006-2009 Christian Helmuth
 * Genode Labs, Feske & Helmuth Systementwicklung GbR
 *
 * This file is part of the Genode OS framework, which is distributed
 * under the terms of the GNU General Public License version 2.
 */

#include <dataspace_component.h>
#include <rm_session_component.h>
#include <pistachio/kip.h>

namespace Pistachio {
#include <l4/types.h>
#include <l4/space.h>
}

using namespace Genode;


/* DEBUGGING */
static const bool verbose = false;


void Dataspace_component::map_page(off_t offset, bool write)
{
	if (verbose)
		PDBG("ds %p map_page (offset = %08lx, %s)", this, offset, 
		     write ? "WRITE" : "READ");

	if ((offset >= 0) && ((unsigned)offset < _size)) {
		if (write)
			Pistachio::touch_rw((void *)(_core_local_addr + offset), 1);
		else
			Pistachio::touch_ro((void *)(_core_local_addr + offset), 1);
	}
}


void Dataspace_component::unmap()
{
	using namespace Pistachio;

	L4_Word_t ps = get_page_size();

	if (verbose)
		PDBG("ds %p unmap [%lx,%lx)", this, _core_local_addr, _core_local_addr + _size);

	for (addr_t addr = _core_local_addr; addr <= _core_local_addr + _size; addr += ps) {
		L4_Fpage_t fp = L4_Fpage(addr, ps);
		L4_Unmap(L4_FpageAddRightsTo(&fp, L4_FullyAccessible));
	}
}


void Dataspace_component::attached_to(Rm_region *region)
{
	Lock::Guard lock_guard(_lock);
	_regions.insert(region);
}


void Dataspace_component::detached_from(Rm_region *region)
{
	Lock::Guard lock_guard(_lock);
	_regions.remove(region);
}


Dataspace_component::~Dataspace_component()
{
	_lock.lock();

	/* remove from all regions */
	while (Rm_region *r = _regions.first()) {

		/*
		 * The 'detach' function calls 'Dataspace_component::detached_from'
		 * and thereby removes the current region from the '_regions' list.
		 */
		_lock.unlock();
		r->session()->detach((void *)r->base());
		_lock.lock();
	}

	_lock.unlock();
}
